﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.Data;
using System.IO;
using System.Collections.Generic;

namespace RMS.Common
{
    public class ExportExcelResult : ActionResult
    {
        #region 构造函数
        /// <summary>
        /// 导出Excel的Result
        /// </summary>
        /// <param name="data">数据</param>
        public ExportExcelResult(IEnumerable<Object> data)
            : this(data, "")
        {
            DateTime time = DateTime.Now;
            this.FileName = string.Format("{0}_{1}_{2}_{3}",
                time.Month, time.Day, time.Hour, time.Minute);
        }
        /// <summary>
        /// 导出Excel的Result
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="fileName">文件名</param>
        public ExportExcelResult(IEnumerable<Object> data, string fileName)
            : this(data, fileName, null)
        {
            this.TitleFormater = p => p;
        }
        /// <summary>
        /// 导出Excel的Result
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="fileName">文件名</param>
        /// <param name="titleFormater">标题格式化</param>
        public ExportExcelResult(IEnumerable<Object> data, string fileName, Func<string, string> titleFormater)
        {
            this.Data = data;
            this.FileName = fileName;
            this.TitleFormater = titleFormater;
        } 
        #endregion

        #region 属性
        /// <summary>
        /// 数据
        /// </summary>
        public IEnumerable<Object> Data
        {
            get;
            set;
        }
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName
        {
            get;
            set;
        }
        /// <summary>
        /// 标题格式化
        /// </summary>
        public Func<string, string> TitleFormater
        {
            get;
            set;
        } 
        #endregion

        /// <summary>
        /// 向客户端输出导出结果
        /// </summary>
        /// <param name="context">控制器上下文</param>
        public override void ExecuteResult(ControllerContext context)
        {
            if (Data == null)
            {
                new EmptyResult().ExecuteResult(context);
                return;
            }

            SetResponse(context);
        }

        /// <summary>
        /// 设置并向客户端发送请求响应
        /// </summary>
        /// <param name="context">控制器上下文</param>
        private void SetResponse(ControllerContext context)
        {

            FileName = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(FileName));

            MemoryStream ms = ConvertToExcel();

            context.HttpContext.Response.Clear();
            context.HttpContext.Response.ClearContent();
            context.HttpContext.Response.Buffer = true;
            context.HttpContext.Response.Charset = "GB2312";
            context.HttpContext.Response.ContentEncoding = Encoding.UTF8;
            context.HttpContext.Response.ContentType = "application/ms-excel";
            context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ".xls");
            context.HttpContext.Response.AddHeader("Content-Length", ms.Length.ToString());
            context.HttpContext.Response.BinaryWrite(ms.ToArray());
            context.HttpContext.Response.End();
        }

        /// <summary>
        /// 把泛型集合转换成Excel表格
        /// </summary>
        /// <returns></returns>
        private MemoryStream ConvertToExcel()
        {
            var ms = new MemoryStream();
            IWorkbook workbook = new HSSFWorkbook();
            ISheet sheet = workbook.CreateSheet("sheet1");

            sheet.DefaultColumnWidth = 15;
            AddTableHead(sheet);
            AddTableBody(sheet);
            workbook.Write(ms);
            ms.Flush();
            ms.Position = 0;
            return ms;
        }

        /// <summary>
        /// 添加Excel表头
        /// </summary>
        /// <param name="sheet">工作薄</param>
        private void AddTableHead(ISheet sheet)
        {
            PropertyDescriptorCollection properties = FindProperties();

            if (properties.Count <= 0)
            {
                return;
            }

            IRow row = sheet.CreateRow(0);//在工作表中添加一行
            //增加序号列
            //ICell cellSerialNumber = row.CreateCell(0);
            //cellSerialNumber.SetCellValue("序号");
            //cellSerialNumber.CellStyle = GetHeadStyle(sheet.Workbook);

            for (int i = 0; i < properties.Count; i++)
            {
                //ICell cell = row.CreateCell(i + 1);//在行中添加一列
                ICell cell = row.CreateCell(i);//在行中添加一列
                string value = properties[i].Name;

                value = TitleFormater(value);

                cell.SetCellValue(value);//设置列的内容
                cell.CellStyle = GetHeadStyle(sheet.Workbook);
            }
        }
        /// <summary>
        /// 添加Excel数据
        /// </summary>
        /// <param name="sheet">工作薄</param>
        private void AddTableBody(ISheet sheet)
        {
            if (Data == null || !this.Data.Any())
            {
                return;
            }
            PropertyDescriptorCollection properties = FindProperties();
            if (properties.Count <= 0)
            {
                return;
            }

            int itemIndex = 0;
            foreach (var item in Data)
            {
                itemIndex++;
                IRow row = sheet.CreateRow(itemIndex);//在工作表中添加一行
                //增加序号列
                //ICell cellSerialNumber = row.CreateCell(0);
                //cellSerialNumber.SetCellValue(itemIndex);
                for (int j = 0; j < properties.Count; j++)
                {

                    object obj = properties[j].GetValue(item);
                    obj = obj == null ? string.Empty : obj.ToString();
                    //ICell cell = row.CreateCell(j + 1);//在行中添加一列
                    ICell cell = row.CreateCell(j);//在行中添加一列
                    //cell.SetCellValue(obj.ToString());//设置列的内容
                    cell.SetCellValue(obj.ToString());//设置列的内容
                }
            }
        }
        /// <summary>
        /// 获取表头样式
        /// </summary>
        /// <param name="workbook">The workbook.</param>
        /// <returns></returns>
        private ICellStyle GetHeadStyle(IWorkbook workbook)
        {
            ICellStyle style = workbook.CreateCellStyle();
            IFont font = workbook.CreateFont();//新建一个字体样式对象
            font.FontHeightInPoints = 11;//字号
            font.FontName = "宋体";//字体
            font.Boldweight = short.MaxValue;//设置字体加粗样式
            style.SetFont(font);//使用SetFont方法将字体样式添加到单元格样式中 
            return style;
        }
        /// <summary>
        /// 返回属性集合(所有列)
        /// </summary>
        /// <returns></returns>
        private PropertyDescriptorCollection FindProperties()
        {
            return TypeDescriptor.GetProperties(Data.FirstOrDefault());
        }
    }
}
